#include "FileRename.h"
#include "ui_FileRename.h"

FileRename::FileRename(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::FileRename)
    , m_pDealPart(new FRDealPart(this))
    , m_pAdjustThread(new FRAdjustThread(this))
    , m_pValidator(new QRegExpValidator(QRegExp(R"([^\\/:*?<>|]+)"), this))
    , m_upThreadPool(new FRThreadPool())
    , m_upModuleFactory(new FRModuleFactory())
    , m_isDirRecursion(false)
    , m_isCaseInsensitivity(false)
{
    ui->setupUi(this);

    // 设置界面初始状态
    SetInitStatus();
    // 设置控件方法ID
    SetObjectMethod();
    // 设置信号与槽连接
    SetObjectConnect();
}

FileRename::~FileRename()
{
    m_upThreadPool->Stop();

    delete ui;
}

void FileRename::SetInitStatus()
{
    // 设置列宽
    ui->tableWidgetFileList->setColumnWidth(FRColumnID::FR_Column_Real, 400);
    ui->tableWidgetFileList->setColumnWidth(FRColumnID::FR_Column_Prefix, 200);
    ui->tableWidgetFileList->setColumnWidth(FRColumnID::FR_Column_Suffix, 200);
    // 设置第4列自动调整列宽
    ui->tableWidgetFileList->horizontalHeader()->setSectionResizeMode(FRColumnID::FR_Column_Dir, QHeaderView::ResizeToContents);

    // 设置整行选中
    ui->tableWidgetFileList->setSelectionBehavior(QAbstractItemView::SelectRows);
    // 设置不可编辑
    ui->tableWidgetFileList->setEditTriggers(QAbstractItemView::NoEditTriggers);
    // 设置右键请求信号
    ui->tableWidgetFileList->setContextMenuPolicy(Qt::CustomContextMenu);

    // 状态栏显示当前文件数量
    ui->statusbar->showMessage(QString("已加载 : %1").arg(0), INT_MAX);

    // 获取所有对象
    QList<QObject *> listObjects = FRCommon::GetAllObjects(this);
    // 获取所有的QLineEdit对象
    QList<QLineEdit *> listLineEdit = FRCommon::GetTargetObjs<QObject, QLineEdit>(listObjects, "lineEdit");
    // 获取所有的QLabel对象
    QList<QLabel *> listLabel = FRCommon::GetTargetObjs<QObject, QLabel>(listObjects, "label");

    // 设置lineEdit可输入合法字符，最大输入长度
    for (QLineEdit *pLineEdit : listLineEdit)
    {
        // 正则表达式框可以输入特殊字符
        if (pLineEdit != ui->lineEditRepRegex && pLineEdit != ui->lineEditRepRegexStr)
        {
            pLineEdit->setValidator(m_pValidator);
        }
        pLineEdit->setMaxLength(128);
        pLineEdit->setFixedWidth(240);
        pLineEdit->setContextMenuPolicy(Qt::NoContextMenu);
    }
    // 将所有QLabel设置为定宽
    for (QLabel *pLabel : listLabel)
    {
        pLabel->setFixedWidth(32);
    }

    // 设置选值框设置统一大小
    ui->spinBoxNumStart->setFixedWidth(90);
    ui->spinBoxNumSpan->setFixedWidth(90);
    ui->spinBoxNumFigure->setFixedWidth(90);

    // tabWidget设置初始界面为第一页
    ui->tabWidgetMode->setCurrentIndex(0);

    // 初始将上一步，下一步设置为非激活
    ui->actionPrevStep->setEnabled(false);
    ui->actionNextStep->setEnabled(false);

    this->setAcceptDrops(true);

    // 子窗口打开时阻塞父窗口
    m_pAdjustThread->setWindowModality(Qt::WindowModal);
    // 设置初始线程数
    m_pAdjustThread->UpdateLCD(m_upThreadPool->GetPoolSize());

    m_upThreadPool->Start();
}

void FileRename::SetObjectMethod()
{
    // 添加模块
    ui->lineEditAddHeadStr->Method(FRAddMethod::FR_Method_Add_Head);
    ui->lineEditAddTailStr->Method(FRAddMethod::FR_Method_Add_Tail);
    ui->lineEditAddSubFront->Method(FRAddMethod::FR_Method_Add_SubFront);
    ui->lineEditAddSubFrontStr->Method(FRAddMethod::FR_Method_Add_SubFront);
    ui->lineEditAddSubBack->Method(FRAddMethod::FR_Method_Add_SubBack);
    ui->lineEditAddSubBackStr->Method(FRAddMethod::FR_Method_Add_SubBack);
    ui->lineEditAddFrontFront->Method(FRAddMethod::FR_Method_Add_SecFront);
    ui->lineEditAddFrontBack->Method(FRAddMethod::FR_Method_Add_SecFront);
    ui->lineEditAddSecFrontStr->Method(FRAddMethod::FR_Method_Add_SecFront);
    ui->lineEditAddBackFront->Method(FRAddMethod::FR_Method_Add_SecBack);
    ui->lineEditAddBackBack->Method(FRAddMethod::FR_Method_Add_SecBack);
    ui->lineEditAddSecBackStr->Method(FRAddMethod::FR_Method_Add_SecBack);

    // 替换模块
    ui->lineEditRepRegex->Method(FRRepMethod::FR_Method_Rep_Regex);
    ui->lineEditRepRegexStr->Method(FRRepMethod::FR_Method_Rep_Regex);
    ui->lineEditRepSub->Method(FRRepMethod::FR_Method_Rep_Sub);
    ui->lineEditRepSubStr->Method(FRRepMethod::FR_Method_Rep_Sub);
    ui->lineEditRepSubFront->Method(FRRepMethod::FR_Method_Rep_SubFront);
    ui->lineEditRepSubFrontStr->Method(FRRepMethod::FR_Method_Rep_SubFront);
    ui->lineEditRepSubBack->Method(FRRepMethod::FR_Method_Rep_SubBack);
    ui->lineEditRepSubBackStr->Method(FRRepMethod::FR_Method_Rep_SubBack);
    ui->lineEditRepSecFront->Method(FRRepMethod::FR_Method_Rep_Sec);
    ui->lineEditRepSecBack->Method(FRRepMethod::FR_Method_Rep_Sec);
    ui->lineEditRepSecStr->Method(FRRepMethod::FR_Method_Rep_Sec);

    // 编号模块
    ui->radioButtonNumHead->Method(FRNumMethod::FR_Method_Num_Head);
    ui->radioButtonNumTail->Method(FRNumMethod::FR_Method_Num_Tail);
    ui->lineEditNumSubFront->Method(FRNumMethod::FR_Method_Num_SubFront);
    ui->lineEditNumSubBack->Method(FRNumMethod::FR_Method_Num_SubBack);
    ui->lineEditNumFrontFront->Method(FRNumMethod::FR_Method_Num_SecFront);
    ui->lineEditNumFrontBack->Method(FRNumMethod::FR_Method_Num_SecFront);
    ui->lineEditNumBackFront->Method(FRNumMethod::FR_Method_Num_SecBack);
    ui->lineEditNumBackBack->Method(FRNumMethod::FR_Method_Num_SecBack);

    // 字母模块
    ui->radioButtonLetUp->Method(FRLetMethod::FR_Method_Let_Up);
    ui->radioButtonLetLow->Method(FRLetMethod::FR_Method_Let_Low);
    ui->lineEditLetSubUp->Method(FRLetMethod::FR_Method_Let_SubUp);
    ui->lineEditLetSubLow->Method(FRLetMethod::FR_Method_Let_SubLow);
    ui->lineEditLetUpFront->Method(FRLetMethod::FR_Method_Let_SecUp);
    ui->lineEditLetUpBack->Method(FRLetMethod::FR_Method_Let_SecUp);
    ui->lineEditLetLowFront->Method(FRLetMethod::FR_Method_Let_SecLow);
    ui->lineEditLetLowBack->Method(FRLetMethod::FR_Method_Let_SecLow);
}

void FileRename::SetObjectConnect()
{
    // 右键菜单
    connect(ui->tableWidgetFileList, &QTableWidget::customContextMenuRequested, this, &FileRename::RightMenu);
    // 表头排序
    connect(ui->tableWidgetFileList->horizontalHeader(), &QHeaderView::sectionClicked, this, &FileRename::UpdateSortTW);
    // 修改线程池线程数量
    connect(m_pAdjustThread, &FRAdjustThread::sizeChange, this, &FileRename::UpdateThreadPoolSize);

    // 添加.头加
    connect(ui->lineEditAddHeadStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddHeadStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 添加.尾加
    connect(ui->lineEditAddTailStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddTailStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 添加.子串之前
    connect(ui->lineEditAddSubFront, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubFrontStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubFront, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubFrontStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 添加.字串之后
    connect(ui->lineEditAddSubBack, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubBackStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubBack, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSubBackStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 添加.区间之前
    connect(ui->lineEditAddFrontFront, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddFrontBack, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSecFrontStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddFrontFront, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddFrontBack, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSecFrontStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 添加.区间之后
    connect(ui->lineEditAddBackFront, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddBackBack, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSecBackStr, &QLineEdit::textEdited, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddBackFront, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddBackBack, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);
    connect(ui->lineEditAddSecBackStr, &FRLineEdit::clicked, this, &FileRename::UpdateAddition);

    // 替换.正则
    connect(ui->lineEditRepRegex, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepRegexStr, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepRegex, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepRegexStr, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);

    // 替换.字串
    connect(ui->lineEditRepSub, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubStr, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSub, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubStr, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);

    // 替换.字串之前
    connect(ui->lineEditRepSubFront, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubFrontStr, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubFront, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubFrontStr, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);

    // 替换.字串之后
    connect(ui->lineEditRepSubBack, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubBackStr, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubBack, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSubBackStr, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);

    // 替换.区间
    connect(ui->lineEditRepSecFront, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSecBack, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSecStr, &QLineEdit::textEdited, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSecFront, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSecBack, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);
    connect(ui->lineEditRepSecStr, &FRLineEdit::clicked, this, &FileRename::UpdateReplace);

    // 编号.整体之前
    connect(ui->radioButtonNumHead, &FRRadioButton::clicked, this, &FileRename::UpdateNumber);

    // 编号.整体之后
    connect(ui->radioButtonNumTail, &FRRadioButton::clicked, this, &FileRename::UpdateNumber);

    // 编号.子串之前
    connect(ui->lineEditNumSubFront, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumSubFront, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);

    // 编号.子串之后
    connect(ui->lineEditNumSubBack, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumSubBack, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);

    // 编号.区间之前
    connect(ui->lineEditNumFrontFront, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumFrontBack, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumFrontFront, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumFrontBack, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);

    // 编号.区间之后
    connect(ui->lineEditNumBackFront, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumBackBack, &FRLineEdit::textChanged, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumBackFront, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);
    connect(ui->lineEditNumBackBack, &FRLineEdit::clicked, this, &FileRename::UpdateNumber);

    // 字母.整体大写
    connect(ui->radioButtonLetUp, &FRRadioButton::clicked, this, &FileRename::UpdateLetter);

    // 字母.整体小写
    connect(ui->radioButtonLetLow, &FRRadioButton::clicked, this, &FileRename::UpdateLetter);

    // 字母.字串大写
    connect(ui->lineEditLetSubUp, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetSubUp, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);

    // 字母.字串小写
    connect(ui->lineEditLetSubLow, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetSubLow, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);

    // 字母.区间大写
    connect(ui->lineEditLetUpFront, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetUpBack, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetUpFront, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetUpBack, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);

    // 字母.区间小写
    connect(ui->lineEditLetLowFront, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetLowBack, &FRLineEdit::textChanged, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetLowFront, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);
    connect(ui->lineEditLetLowBack, &FRLineEdit::clicked, this, &FileRename::UpdateLetter);
}

void FileRename::InsertTW(const QList<FRFileInfo> &c_listFI, const int c_index)
{
    // 当前选择插入的行数小于0则以最后一行为起始行，否则以选择行为起始行
    int currentRow = c_index < 0 ? ui->tableWidgetFileList->rowCount() : c_index;

    for (const FRFileInfo &c_fi : c_listFI)
    {
        // 在当前行前插入一行
        ui->tableWidgetFileList->insertRow(currentRow);

        // 在插入和行插入单元格，并设置值
        ui->tableWidgetFileList->setItem(currentRow, FRColumnID::FR_Column_Real, new QTableWidgetItem(c_fi.RealName()));
        ui->tableWidgetFileList->setItem(currentRow, FRColumnID::FR_Column_Prefix, new QTableWidgetItem(c_fi.TempPrefix()));
        ui->tableWidgetFileList->setItem(currentRow, FRColumnID::FR_Column_Suffix, new QTableWidgetItem(c_fi.TempSuffix()));
        ui->tableWidgetFileList->setItem(currentRow, FRColumnID::FR_Column_Dir, new QTableWidgetItem(c_fi.Directory()));

        // 将单元格对齐方式设置为右对齐，垂直居中
        ui->tableWidgetFileList->item(currentRow, FRColumnID::FR_Column_Real)->setTextAlignment(
                    Qt::AlignRight | Qt::AlignVCenter);
        ui->tableWidgetFileList->item(currentRow, FRColumnID::FR_Column_Prefix)->setTextAlignment(
                    Qt::AlignRight | Qt::AlignVCenter);
        ui->tableWidgetFileList->item(currentRow, FRColumnID::FR_Column_Suffix)->setTextAlignment(
                    Qt::AlignRight | Qt::AlignVCenter);
        ui->tableWidgetFileList->item(currentRow, FRColumnID::FR_Column_Dir)->setTextAlignment(
                    Qt::AlignRight | Qt::AlignVCenter);

        currentRow++;
    }
}

void FileRename::RemoveTWRows(const QList<int> &c_listRow)
{
    for (int i = 0; i < c_listRow.size(); i++)
    {
        ui->tableWidgetFileList->removeRow(c_listRow[i] - i);
    }
}

QList<int> FileRename::GetSelectRows()
{
    QList<int> listIndex;
    // 获取选中行的范围
    QList<QTableWidgetSelectionRange> listRanges = ui->tableWidgetFileList->selectedRanges();

    for(int i = 0; i < listRanges.size(); i++)
    {
        int topRow = listRanges.at(i).topRow();
        int bottomRow = listRanges.at(i).bottomRow();

        for (int j = topRow; j <= bottomRow; j++)
        {
            listIndex.push_back(j);
        }
    }
    // 对选中的行进行排序
    std::sort(listIndex.begin(), listIndex.end());

    return listIndex;
}

bool FileRename::SwapRows(const int c_iRowFirst, const int c_iRowSecond)
{
    // 获取tablewidget最大行索引
    int maxRowIndex = ui->tableWidgetFileList->rowCount() - 1;
    QString qstrTemp;

    if (c_iRowFirst < 0 || c_iRowFirst > maxRowIndex || c_iRowSecond < 0 || c_iRowSecond > maxRowIndex)
    {
        return false;
    }
    QTableWidgetItem *itemRealFirst = ui->tableWidgetFileList->item(c_iRowFirst, FRColumnID::FR_Column_Real);
    QTableWidgetItem *itemPrefixFirst = ui->tableWidgetFileList->item(c_iRowFirst, FRColumnID::FR_Column_Prefix);
    QTableWidgetItem *itemSuffixFirst = ui->tableWidgetFileList->item(c_iRowFirst, FRColumnID::FR_Column_Suffix);
    QTableWidgetItem *itemDirFirst = ui->tableWidgetFileList->item(c_iRowFirst, FRColumnID::FR_Column_Dir);

    QTableWidgetItem *itemRealSecond = ui->tableWidgetFileList->item(c_iRowSecond, FRColumnID::FR_Column_Real);
    QTableWidgetItem *itemPrefixSecond = ui->tableWidgetFileList->item(c_iRowSecond, FRColumnID::FR_Column_Prefix);
    QTableWidgetItem *itemSuffixSecond = ui->tableWidgetFileList->item(c_iRowSecond, FRColumnID::FR_Column_Suffix);
    QTableWidgetItem *itemDirSecond = ui->tableWidgetFileList->item(c_iRowSecond, FRColumnID::FR_Column_Dir);

    // 交换内容
    qstrTemp = itemRealFirst->text();
    itemRealFirst->setText(itemRealSecond->text());
    itemRealSecond->setText(qstrTemp);

    qstrTemp = itemPrefixFirst->text();
    itemPrefixFirst->setText(itemPrefixSecond->text());
    itemPrefixSecond->setText(qstrTemp);

    qstrTemp =  itemSuffixFirst->text();
    itemSuffixFirst->setText(itemSuffixSecond->text());
    itemSuffixSecond->setText(qstrTemp);

    qstrTemp = itemDirFirst->text();
    itemDirFirst->setText(itemDirSecond->text());
    itemDirSecond->setText(qstrTemp);

    return true;
}

QStringList FileRename::GetFileDialogSelect(QFileDialog::FileMode fileMode)
{
    QStringList listSelect;

    QFileDialog *fileDialog = new QFileDialog(this);

    // 设置文件框过滤模式
    fileDialog->setFileMode(fileMode);
    fileDialog->setOption(QFileDialog::DontResolveSymlinks);

    if (fileDialog->exec())
    {
        listSelect = fileDialog->selectedFiles();
    }

    return listSelect;
}

void FileRename::AnalyzeSelect(QList<QString> &listSelect, QList<FRFileInfo> &listAnalyzeFI, bool isRecursion)
{
    for (int i = 0; i < listSelect.size(); i++)
    {
        QFileInfo selectInfo(listSelect[i]);

        if (selectInfo.isFile())
        {
            listAnalyzeFI.append(listSelect[i]);
        }
        else if (selectInfo.isDir())
        {
            QList<QString> listSub;
            QDir dirSub(listSelect[i]);

            // 若递归则获取子目录存入选择之中
            if (isRecursion)
            {
                listSub = dirSub.entryList(QDir::Dirs | QDir::NoDotAndDotDot);
                std::for_each(listSub.begin(), listSub.end(), [&](QString &qstrSub) {
                    listSelect.append(qstrSub.prepend(listSelect[i] + FR_SLASH));
                });
            }

            // 获取目录下的文件存入分析之中
            listSub = dirSub.entryList(QDir::Files);
            std::for_each(listSub.begin(), listSub.end(), [&](QString &qstrSub) {
                listAnalyzeFI.append(qstrSub.prepend(listSelect[i] + FR_SLASH));
            });
        }
    }
}

void FileRename::DealRepeatFI(QList<FRFileInfo> &listFI, QList<FRFileInfo> &listRealFI,
                              QList<FRFileInfo> &listResultFI)
{
    std::sort(listFI.begin(), listFI.end());
    // 删除listFI中的重复项
    listFI.erase(std::unique(listFI.begin(), listFI.end()), listFI.end());

    // 若不存在已添加的文件信息，则直接移动到listResultFI
    if (listRealFI.isEmpty())
    {
        listResultFI = std::move(listFI);
    }
    else
    {
        std::sort(listRealFI.begin(), listRealFI.end());
        // 将存在于listFI当不存在listRealFI的文件添加到listResultFI
        std::set_difference(listFI.begin(), listFI.end(), listRealFI.begin(), listRealFI.end(),
                            std::back_inserter(listResultFI));
    }
}

void FileRename::InsertFI(const QList<FRFileInfo> &c_listFI, const int c_index)
{
    // 恢复临时名称
    UpdateRefresh();
    // 恢复单选框
    UpdateRadioButton();
    // 插入文件信息
    FRDealFile::GetInstance().Insert(c_listFI, c_index);
    InsertTW(c_listFI, c_index);
    // 插入历史信息
    FRHistory::GetInstance().InsertNewFI(c_listFI);
    UpdateStep();
    ui->statusbar->showMessage(QString("已加载 : %1").arg(FRDealFile::GetInstance().Size()));
}

void FileRename::Modify(FRModuleParam &moduleParam)
{
    QList<FRFileInfo> listFI = FRDealFile::GetInstance().GetFileInfo();

    if (listFI.isEmpty())
    {
        return;
    }

    // 获取模块对象
    std::shared_ptr<FRModule> spModule = m_upModuleFactory->GetModule(moduleParam.eModule);

    if (m_pDealPart->DealPartMode() == FRDealPartMode::FR_DealPart_Prefix)
    {
        for (FRFileInfo &fi : listFI)
        {
            fi.ModifyToReal();
            spModule->Modify(moduleParam, fi.TempPrefixRef());
        }
    }
    else
    {
        for (FRFileInfo &fi : listFI)
        {
            fi.ModifyToReal();
            spModule->Modify(moduleParam, fi.TempSuffixRef());
        }
    }

    FRDealFile::GetInstance().SetFileInfo(listFI);
    UpdateTWColumn(FR_COLUMNTYPE_PREFIX | FR_COLUMNTYPE_SUFFIX);
}

void FileRename::on_actionOpenFiles_triggered()
{
    // 选中的文件路径
    QStringList listSelect = GetFileDialogSelect(QFileDialog::ExistingFiles);

    if (!listSelect.isEmpty())
    {
        // 已经存储的文件信息
        QList<FRFileInfo> listRealFI = FRDealFile::GetInstance().GetFileInfo();
        // 分析出来的文件信息
        QList<FRFileInfo> listAnalyzeFI;
        // 实际添加的文件信息
        QList<FRFileInfo> listResultFI;

        // 处理获取的文件对象
        AnalyzeSelect(listSelect, listAnalyzeFI);
        // 处理重复文件信息
        DealRepeatFI(listAnalyzeFI, listRealFI, listResultFI);
        // 插入文件信息
        InsertFI(listResultFI);
    }
}

void FileRename::on_actionOpenFolder_triggered()
{
    QStringList listSelect = GetFileDialogSelect(QFileDialog::DirectoryOnly);

    if (!listSelect.isEmpty())
    {
        QList<FRFileInfo> listRealFI = FRDealFile::GetInstance().GetFileInfo();
        QList<FRFileInfo> listAnalyzeFI;
        QList<FRFileInfo> listResultFI;

        AnalyzeSelect(listSelect, listAnalyzeFI, m_isDirRecursion);
        DealRepeatFI(listAnalyzeFI, listRealFI, listResultFI);
        InsertFI(listResultFI);
    }
}

void FileRename::on_actionClearAllFiles_triggered()
{
    // 清空所有文件
    FRDealFile::GetInstance().Clear();
    // 清空tablewidget所有的内容
    ui->tableWidgetFileList->clearContents();
    // 将tablewidget的行数设置为0
    ui->tableWidgetFileList->setRowCount(0);
    // 清空历史记录
    FRHistory::GetInstance().Clear();
    // 更新上下步按钮状态
    UpdateStep();

    ui->statusbar->showMessage(QString("已加载 : %1").arg(0));
}

void FileRename::on_actionHistoryClear_triggered()
{
    if (FRDealFile::GetInstance().Size() != 0)
    {
        FRHistory::GetInstance().Clear();
        FRHistory::GetInstance().InsertNewFI(FRDealFile::GetInstance().GetFileInfo());
        UpdateStep();
    }
}

void FileRename::on_actionPrevStep_triggered()
{
    FRHistory::GetInstance().ReduceIndex();
    UpdateHistory();
    UpdateStep();
}

void FileRename::on_actionNextStep_triggered()
{
    FRHistory::GetInstance().IncreaseIndex();
    UpdateHistory();
    UpdateStep();
}

void FileRename::on_actionRefresh_triggered()
{
    UpdateRefresh();
}

void FileRename::on_actionClearAllCommand_triggered()
{
    UpdateRadioButton();
    QList<QObject *> listObj = FRCommon::GetAllObjects(this);
    QList<QLineEdit *> listLineEdit = FRCommon::GetTargetObjs<QObject, QLineEdit>(listObj, "lineEdit");

    // 将所有QLineEdit控件内容清空
    for (QLineEdit *pLineEdit : listLineEdit)
    {
        pLineEdit->clear();
    }

    ui->spinBoxNumStart->setValue(1);
    ui->spinBoxNumFigure->setValue(1);
    ui->spinBoxNumSpan->setValue(1);

    UpdateRefresh();
}

void FileRename::on_actionSureModify_triggered()
{
    QList<FRFileInfo> listFI = FRDealFile::GetInstance().GetFileInfo();

    if (listFI.isEmpty())
    {
        return;
    }

    std::map<FRFileInfo, std::future<FRFileInfo>> tempMapFIFu;  // 储存返回的期望
    bool isModify = false;      // 标记是否有文件被修改

    for (FRFileInfo &fi : listFI)
    {
        // 记录修改之前的文件信息
        FRFileInfo oldFI(fi);

        std::future<FRFileInfo> fuFI = m_upThreadPool->AddTask([&fi]() {
            if (fi.RealName() != fi.TempPrefix() + FR_POINT + fi.TempSuffix())
            {
                QString tempFilePath = fi.Directory() + FR_SLASH + fi.TempPrefix() +
                        (fi.TempSuffix().isEmpty() ? "" : FR_POINT + fi.TempSuffix());

                // 更名成功则同为临时名称，否则同为真实名称
                if (QFile::rename(fi.Directory() + FR_SLASH + fi.RealName(), tempFilePath))
                {
                    fi.ModifyToTemp();

                    // 若输入.则后缀有变化需重新更新
                    FilePreSuf file = fi.SplitPreSuf();

                    fi.TempPrefixRef() = file.first;
                    fi.TempSuffixRef() = file.second;
                }
                else
                {
                    fi.ModifyToReal();
                }
            }

            return fi;
        });
        // 储存期望
        tempMapFIFu[oldFI] = std::move(fuFI);
    }

    // 修改之后的名称（此次名称）作为真实名称，修改之前的名称（上次名称）作为临时名称
    QList<FRRecordFI> tempListRecordFI;     // 储存单次历史更改

    for (decltype(tempMapFIFu)::iterator it = tempMapFIFu.begin(); it != tempMapFIFu.end(); it++)
    {
        FRRecordFI rfi;

        // 处理之后的名称作为当前名称
        rfi.currentName = it->second.get().RealName();
        // 以临时名称作为上次名称
        rfi.lastName = it->first.RealName();
        // 路径不变
        rfi.directory = it->first.Directory();
        // 储存单次记录
        tempListRecordFI.append(rfi);

        // 上次真实名称和此次真实名称有不同即有文件的名称发生了修改
        if (!isModify && rfi.currentName != rfi.lastName)
        {
            isModify = true;
        }
    }

    if (isModify)
    {
        // 清空储存中的文件
        FRDealFile::GetInstance().Clear();
        // 添加重命名后的文件
        FRDealFile::GetInstance().Insert(listFI);
        // 添加历史信息
        FRHistory::GetInstance().SetRecord(tempListRecordFI);
        // 更新上下步按钮状态
        UpdateStep();
    }

    UpdateTWColumn(FR_COLUMNTYPE_REAL | FR_COLUMNTYPE_PREFIX | FR_COLUMNTYPE_SUFFIX);
    UpdateRadioButton();
}

void FileRename::on_actionDirRecursion_triggered()
{
    m_isDirRecursion = !m_isDirRecursion;
    ui->actionDirRecursion->setChecked(m_isDirRecursion);
}

void FileRename::on_actionCaseInsensitivity_triggered()
{
    m_isCaseInsensitivity = !m_isCaseInsensitivity;
    ui->actionCaseInsensitivity->setChecked(m_isCaseInsensitivity);
}

void FileRename::on_actionDealPart_triggered()
{
    m_pDealPart->show();
}

void FileRename::on_actionAdjustThread_triggered()
{
    // 更新LCD显示
    m_pAdjustThread->UpdateLCD();
    m_pAdjustThread->show();
}

void FileRename::on_actionCodeAddress_triggered()
{
    // 打开链接
    QDesktopServices::openUrl(QUrl("https://gitee.com/LinuxShaZi/file_rename.git"));
}

void FileRename::on_actionAboutSoft_triggered()
{
    QMessageBox *pMsgBox = new QMessageBox(this);
    pMsgBox->setWindowIcon(QIcon(":/image/about.png"));
    pMsgBox->setWindowTitle("关于软件");
    pMsgBox->setText("<font face=Consolas size=24>v1.05<br>尚待优化！</font>");
    pMsgBox->exec();
}

void FileRename::dragEnterEvent(QDragEnterEvent *event)
{
    if (event->mimeData()->hasUrls())
    {
        event->acceptProposedAction();
    }
    else
    {
        event->ignore();
    }
}

void FileRename::dropEvent(QDropEvent* event)
{
    const QMimeData* mimeData = event->mimeData();
    if(mimeData->hasUrls())
    {
        // 获取文件地址
        QList<QUrl> urlList = mimeData->urls();
        QStringList listSelect;

        for (auto &url : urlList)
        {
            listSelect.push_back(url.toLocalFile());
        }

        if (!listSelect.isEmpty())
        {
            QList<FRFileInfo> listRealFI = FRDealFile::GetInstance().GetFileInfo();
            QList<FRFileInfo> listAnalyzeFI;
            QList<FRFileInfo> listResultFI;

            AnalyzeSelect(listSelect, listAnalyzeFI);
            DealRepeatFI(listAnalyzeFI, listRealFI, listResultFI);
            InsertFI(listResultFI);
        }
    }
}

void FileRename::UpdateTWColumn(const int c_type)
{
    FRDealFile &dealFile = FRDealFile::GetInstance();
    int size = dealFile.Size();

    for (int i = 0; i < size; i++)
    {
        if (c_type & FR_COLUMNTYPE_REAL)
        {
            ui->tableWidgetFileList->item(i, FRColumnID::FR_Column_Real)->setText(dealFile.Index(i).RealName());
        }
        if (c_type & FR_COLUMNTYPE_PREFIX)
        {
            ui->tableWidgetFileList->item(i, FRColumnID::FR_Column_Prefix)->setText(dealFile.Index(i).TempPrefix());
        }
        if (c_type & FR_COLUMNTYPE_SUFFIX)
        {
            ui->tableWidgetFileList->item(i, FRColumnID::FR_Column_Suffix)->setText(dealFile.Index(i).TempSuffix());
        }
        if (c_type & FR_COLUMNTYPE_DIR)
        {
            ui->tableWidgetFileList->item(i, FRColumnID::FR_Column_Dir)->setText(dealFile.Index(i).Directory());
        }
    }
}

void FileRename::UpdateSortTW(const int c_column)
{
    // 标记是否升排序
    static bool isAscend = true;

    if (ui->tableWidgetFileList->rowCount() == 0)
    {
        return;
    }

    // 若当前为升排序则改为降排序，否则改为升排序
    isAscend = !isAscend;

    if (isAscend)
    {
        ui->tableWidgetFileList->sortItems(c_column, Qt::SortOrder::AscendingOrder);
    }
    else
    {
        ui->tableWidgetFileList->sortItems(c_column, Qt::SortOrder::DescendingOrder);
    }
    FRDealFile::GetInstance().Sort(c_column, isAscend);
}

void FileRename::UpdateRefresh()
{
    FRDealFile::GetInstance().Recover();
    UpdateTWColumn(FR_COLUMNTYPE_PREFIX | FR_COLUMNTYPE_SUFFIX);
}

void FileRename::UpdateRadioButton()
{
    ui->radioButtonNumHead->setAutoExclusive(false);
    ui->radioButtonNumTail->setAutoExclusive(false);
    ui->radioButtonLetUp->setAutoExclusive(false);
    ui->radioButtonLetLow->setAutoExclusive(false);

    ui->radioButtonNumHead->setChecked(false);
    ui->radioButtonNumTail->setChecked(false);
    ui->radioButtonLetUp->setChecked(false);
    ui->radioButtonLetLow->setChecked(false);

    ui->radioButtonNumHead->setAutoExclusive(true);
    ui->radioButtonNumTail->setAutoExclusive(true);
    ui->radioButtonLetUp->setAutoExclusive(true);
    ui->radioButtonLetLow->setAutoExclusive(true);
}

void FileRename::UpdateStep()
{
    int currenIndex = FRHistory::GetInstance().CurrentIndex();
    int historySize = FRHistory::GetInstance().Size();

    // 当存储的历史信息为0或者1时将上下步均置为不启用
    if (0 == historySize || 1 == historySize)
    {
        ui->actionPrevStep->setEnabled(false);
        ui->actionNextStep->setEnabled(false);
    }
    else
    {
        if (0 == currenIndex)
        {
            ui->actionPrevStep->setEnabled(false);
            ui->actionNextStep->setEnabled(true);
        }
        else if (historySize - 1 == currenIndex)
        {
            ui->actionPrevStep->setEnabled(true);
            ui->actionNextStep->setEnabled(false);
        }
        else
        {
            ui->actionPrevStep->setEnabled(true);
            ui->actionNextStep->setEnabled(true);
        }
    }
}

void FileRename::UpdateHistory()
{
    QList<FRRecordFI> listRecordFI = FRHistory::GetInstance().GetRecord();
    QList<FRFileInfo> tempListFI;

    for (const FRRecordFI &c_rfi : listRecordFI)
    {
        // 当前名称作为真实名称，上次名称作为临时名称
        tempListFI.push_back(FRFileInfo(c_rfi.directory + FR_SLASH + c_rfi.lastName));
        tempListFI.back().RealNameRef() = c_rfi.currentName;
    }

    FRDealFile::GetInstance().Clear();
    FRDealFile::GetInstance().Insert(tempListFI);

    // 置所有radioButton为初始状态
    UpdateRadioButton();
    // 更新所有列
    UpdateTWColumn(FR_COLUMNTYPE_REAL | FR_COLUMNTYPE_PREFIX | FR_COLUMNTYPE_SUFFIX | FR_COLUMNTYPE_DIR);
}

void FileRename::UpdateThreadPoolSize(const int c_size)
{
    // 先停止线程池后调整线程数，再启动线程池
    m_upThreadPool->Stop();
    m_upThreadPool->ResizePool(c_size);
    m_upThreadPool->Start();
}

void FileRename::RightMenu(const QPoint &c_point)
{
    QMenu *qRightMenu = new QMenu(ui->tableWidgetFileList);
    QAction *qActionAdd = new QAction(QIcon(":/image/add.png"), "添加", ui->tableWidgetFileList);
    QAction *qActionRemove = new QAction(QIcon(":/image/sub.png"), "移除", ui->tableWidgetFileList);
    QAction *qActionUp = new QAction(QIcon(":/image/up.png"), "上移", ui->tableWidgetFileList);
    QAction *qActionDown = new QAction(QIcon(":/image/down.png"), "下移", ui->tableWidgetFileList);

    qRightMenu->addAction(qActionAdd);
    qRightMenu->addAction(qActionRemove);
    qRightMenu->addAction(qActionUp);
    qRightMenu->addAction(qActionDown);

    qRightMenu->move(cursor().pos());
    qRightMenu->show ();

    // 获取当前行
    static int iClickRow = -1;

    iClickRow = ui->tableWidgetFileList->indexAt(c_point).row();

    connect(qActionAdd, &QAction::triggered, [&]{
        QStringList listSelect = GetFileDialogSelect(QFileDialog::ExistingFiles);

        if (!listSelect.isEmpty())
        {
            QList<FRFileInfo> listRealFI = FRDealFile::GetInstance().GetFileInfo();
            QList<FRFileInfo> listAnalyzeFI;
            QList<FRFileInfo> listResultFI;

            AnalyzeSelect(listSelect, listAnalyzeFI);
            DealRepeatFI(listAnalyzeFI, listRealFI, listResultFI);
            InsertFI(listResultFI, iClickRow);
        }
    });

    connect(qActionRemove, &QAction::triggered, [&]{
        QList<int> listIndex = GetSelectRows();
        QList<FRFileInfo> listFI;

        if (!listIndex.empty())
        {
            // 获取要删除索引处的文件信息
            std::for_each(listIndex.begin(), listIndex.end(), [&](int index) {
                listFI.append(FRDealFile::GetInstance().GetFileInfo(index));
            });

            // 从信息储存中删除选中项
            FRDealFile::GetInstance().Remove(listIndex);
            // 从界面中删除选中项
            RemoveTWRows(listIndex);
            // 从历史信息中删去选中项
            FRHistory::GetInstance().RemoveOldFI(listFI);
            UpdateStep();
            ui->statusbar->showMessage(QString("已加载 : %1").arg(FRDealFile::GetInstance().Size()));
        }
    });

    connect(qActionUp, &QAction::triggered, [&]{
        // 当前行上移与上一行交换
        if (SwapRows(iClickRow, iClickRow - 1))
        {
            FRDealFile::GetInstance().Swap(iClickRow, iClickRow - 1);
        }
    });
    connect(qActionDown, &QAction::triggered, [&]{
        // 当前行下移与下一行交换
        if (SwapRows(iClickRow, iClickRow + 1))
        {
            FRDealFile::GetInstance().Swap(iClickRow, iClickRow + 1);
        }
    });
}

void FileRename::UpdateAddition()
{
    QObject *senderObj = QObject::sender();
    FRLineEdit *lineEdit = nullptr;

    // 转换为FRLineEdit类型获取方法ID
    if ((lineEdit = dynamic_cast<FRLineEdit *>(senderObj)) == nullptr)
    {
        QMessageBox::critical(this, "警告", "添加模块信号异常");
        return;
    }

    FRAddParam addParam;

    addParam.eModule = FRModuleType::FR_Module_Addition;
    addParam.eAddMethod = static_cast<FRAddMethod>(lineEdit->Method());
    addParam.eCase = m_isCaseInsensitivity ? Qt::CaseInsensitive : Qt::CaseSensitive;

    // 依据不同的方法获取不同的参数
    switch (addParam.eAddMethod)
    {
    case FRAddMethod::FR_Method_Add_Head:
        addParam.qstrAddHeadStr = ui->lineEditAddHeadStr->text();
        break;
    case FRAddMethod::FR_Method_Add_Tail:
        addParam.qstrAddTailStr = ui->lineEditAddTailStr->text();
        break;
    case FRAddMethod::FR_Method_Add_SubFront:
        addParam.qstrAddSubFront = ui->lineEditAddSubFront->text();
        addParam.qstrAddSubFrontStr = ui->lineEditAddSubFrontStr->text();
        break;
    case FRAddMethod::FR_Method_Add_SubBack:
        addParam.qstrAddSubBack = ui->lineEditAddSubBack->text();
        addParam.qstrAddSubBackStr = ui->lineEditAddSubBackStr->text();
        break;
    case FRAddMethod::FR_Method_Add_SecFront:
        addParam.qstrAddFrontFront = ui->lineEditAddFrontFront->text();
        addParam.qstrAddFrontBack = ui->lineEditAddFrontBack->text();
        addParam.qstrAddSecFrontStr = ui->lineEditAddSecFrontStr->text();
        break;
    case FRAddMethod::FR_Method_Add_SecBack:
        addParam.qstrAddBackFront = ui->lineEditAddBackFront->text();
        addParam.qstrAddBackBack = ui->lineEditAddBackBack->text();
        addParam.qstrAddSecBackStr = ui->lineEditAddSecBackStr->text();
        break;
    default:
        QMessageBox::critical(this, "警告", "添加模块方法异常");
        return;
    }

    Modify(addParam);
}

void FileRename::UpdateReplace()
{
    QObject *senderObj = QObject::sender();
    FRLineEdit *lineEdit = nullptr;

    if ((lineEdit = dynamic_cast<FRLineEdit *>(senderObj)) == nullptr)
    {
        QMessageBox::critical(this, "警告", "替换模块信号异常");
        return;
    }

    FRRepParam repParam;

    repParam.eModule = FRModuleType::FR_Module_Replace;
    repParam.eRepMethod = static_cast<FRRepMethod>(lineEdit->Method());
    repParam.eCase = m_isCaseInsensitivity ? Qt::CaseInsensitive : Qt::CaseSensitive;

    switch (repParam.eRepMethod)
    {
    case FRRepMethod::FR_Method_Rep_Regex:
        repParam.qstrRepRegex = ui->lineEditRepRegex->text();
        repParam.qstrRepRegexStr = ui->lineEditRepRegexStr->text();
        break;
    case FRRepMethod::FR_Method_Rep_Sub:
        repParam.qstrRepSub = ui->lineEditRepSub->text();
        repParam.qstrRepSubStr = ui->lineEditRepSubStr->text();
        break;
    case FRRepMethod::FR_Method_Rep_SubFront:
        repParam.qstrRepSubFront = ui->lineEditRepSubFront->text();
        repParam.qstrRepSubFrontStr = ui->lineEditRepSubFrontStr->text();
        break;
    case FRRepMethod::FR_Method_Rep_SubBack:
        repParam.qstrRepSubBack = ui->lineEditRepSubBack->text();
        repParam.qstrRepSubBackStr = ui->lineEditRepSubBackStr->text();
        break;
    case FRRepMethod::FR_Method_Rep_Sec:
        repParam.qstrRepSecFront = ui->lineEditRepSecFront->text();
        repParam.qstrRepSecBack = ui->lineEditRepSecBack->text();
        repParam.qstrRepSecStr = ui->lineEditRepSecStr->text();
        break;
    default:
        QMessageBox::critical(this, "警告", "替换模块方法异常");
        return;
    }

    Modify(repParam);
}

void FileRename::UpdateNumber()
{
    QObject *senderObj = QObject::sender();
    FRLineEdit *lineEdit = nullptr;
    FRRadioButton *radioButton = nullptr;
    int method = -1;

    if ((lineEdit = dynamic_cast<FRLineEdit *>(senderObj)) != nullptr)
    {
        method = lineEdit->Method();
    }
    else if ((radioButton = dynamic_cast<FRRadioButton *>(senderObj)) != nullptr)
    {
        method = radioButton->Method();
    }
    else
    {
        QMessageBox::critical(this, "警告", "字母模块信号异常");
        return;
    }

    FRNumParam numParam;

    numParam.eModule = FRModuleType::FR_Module_Number;
    numParam.eNumMethod = static_cast<FRNumMethod>(method);
    numParam.eCase = m_isCaseInsensitivity ? Qt::CaseInsensitive : Qt::CaseSensitive;

    numParam.iNumStart = ui->spinBoxNumStart->value();
    numParam.iNumSpan = ui->spinBoxNumSpan->value();
    numParam.iNumFigure = ui->spinBoxNumFigure->value();
    numParam.iNumber = numParam.iNumStart;

    switch (numParam.eNumMethod)
    {
    case FRNumMethod::FR_Method_Num_Head:
        break;
    case FRNumMethod::FR_Method_Num_Tail:
        break;
    case FRNumMethod::FR_Method_Num_SubFront:
        numParam.qstrNumSubFront = ui->lineEditNumSubFront->text();
        break;
    case FRNumMethod::FR_Method_Num_SubBack:
        numParam.qstrNumSubBack = ui->lineEditNumSubBack->text();
        break;
    case FRNumMethod::FR_Method_Num_SecFront:
        numParam.qstrNumFrontFront = ui->lineEditNumFrontFront->text();
        numParam.qstrNumFrontBack = ui->lineEditNumFrontBack->text();
        break;
    case FRNumMethod::FR_Method_Num_SecBack:
        numParam.qstrNumBackFront = ui->lineEditNumBackFront->text();
        numParam.qstrNumBackBack = ui->lineEditNumBackBack->text();
        break;
    default:
        QMessageBox::critical(this, "警告", "替换模块方法异常");
        return;
    }

    Modify(numParam);
}

void FileRename::UpdateLetter()
{
    QObject *senderObj = QObject::sender();
    FRLineEdit *lineEdit = nullptr;
    FRRadioButton *radioButton = nullptr;
    int method = -1;

    if ((lineEdit = dynamic_cast<FRLineEdit *>(senderObj)) != nullptr)
    {
        method = lineEdit->Method();
    }
    else if ((radioButton = dynamic_cast<FRRadioButton *>(senderObj)) != nullptr)
    {
        method = radioButton->Method();
    }
    else
    {
        QMessageBox::critical(this, "警告", "字母模块信号异常");
        return;
    }

    FRLetParam letParam;

    letParam.eModule = FRModuleType::FR_Module_Letter;
    letParam.eLetMethod = static_cast<FRLetMethod>(method);
    letParam.eCase = m_isCaseInsensitivity ? Qt::CaseInsensitive : Qt::CaseSensitive;

    switch (letParam.eLetMethod)
    {
    case FRLetMethod::FR_Method_Let_Up:
        break;
    case FRLetMethod::FR_Method_Let_Low:
        break;
    case FRLetMethod::FR_Method_Let_SubUp:
        letParam.qstrLetSubUp = ui->lineEditLetSubUp->text();
        break;
    case FRLetMethod::FR_Method_Let_SubLow:
        letParam.qstrLetSubLow = ui->lineEditLetSubLow->text();
        break;
    case FRLetMethod::FR_Method_Let_SecUp:
        letParam.qstrLetUpFront = ui->lineEditLetUpFront->text();
        letParam.qstrLetUpBack = ui->lineEditLetUpBack->text();
        break;
    case FRLetMethod::FR_Method_Let_SecLow:
        letParam.qstrLetLowFront = ui->lineEditLetLowFront->text();
        letParam.qstrLetLowBack = ui->lineEditLetLowBack->text();
        break;
    default:
        QMessageBox::critical(this, "警告", "字母模块方法异常");
        return;
    }

    Modify(letParam);
}
